package com.delivery.deliverysystem.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.delivery.deliverysystem.common.FieldDisplay;
import com.delivery.deliverysystem.common.ResponseCode;
import com.delivery.deliverysystem.common.ServerResponse;
import com.delivery.deliverysystem.dao.DefaultNameMapper;
import com.delivery.deliverysystem.dao.SystemLogMapper;
import com.delivery.deliverysystem.exception.RException;
import com.delivery.deliverysystem.pojo.DAO.UserDTO;
import com.delivery.deliverysystem.pojo.DO.DefaultName;
import com.delivery.deliverysystem.pojo.DO.SystemLog;
import com.delivery.deliverysystem.pojo.DO.User;
import com.delivery.deliverysystem.pojo.VO.UserVO;
import com.delivery.deliverysystem.service.SystemLogService;
import com.delivery.deliverysystem.service.UserService;
import com.delivery.deliverysystem.dao.UserMapper;
import com.delivery.deliverysystem.shiro.JWTToken;
import com.delivery.deliverysystem.util.JWTUtil;
import com.delivery.deliverysystem.util.PasswordUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.delivery.deliverysystem.util.PasswordUtil.sha1Encode;

/**
* @author Administrator
* @description 针对表【user(用户管理表)】的数据库操作Service实现
* @createDate 2025-01-13 15:37:40
*/
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
    implements UserService{

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private SystemLogMapper systemLogMapper;

    @Autowired
    private DefaultNameMapper defaultNameMapper;

    @Override
    public ServerResponse createUser(UserDTO userDTO) {
        String code = userDTO.getCode();
        //用户代码唯一 查找该用户代码是否存在
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("user_code",code);
        User user = userMapper.selectOne(wrapper);
        if(user!=null) return ServerResponse.createByError("用户代码已存在");
        String name = userDTO.getName();
        String password = userDTO.getPassword();
        //新增用户的默认字段，转为json传进字段中
        List<DefaultName> defaultNames = defaultNameMapper.selectList(null);
        Map<String,Object> UserDefaultName = new HashMap<>();
        for (DefaultName defaultName:defaultNames){
            String defaultName1 = defaultName.getDefaultName();
            UserDefaultName.put(defaultName1,defaultName1);
        }
        String jsonString = JSONObject.toJSONString(UserDefaultName);
        String deliveryDisplay = FieldDisplay.DELIVERY_DISPLAY;
        String productDisplay = FieldDisplay.PRODUCT_DISPLAY;
        //获取当时登录的用户
        String token = JWTUtil.getCurrentToken();
        if(token==null){
            log.warn("token为空");
            return ServerResponse.createByError("未获取当前登录用户，token为空");
        }
        //获取出来的是用户代码
        String username = JWTUtil.getUsername(token);
        User operator = userMapper.selectOne(new QueryWrapper<User>().eq("user_code", username));
        User u = null;
        if(code!=null && name!=null && password!=null){
            //密码加密
            String encode = sha1Encode(password);
            u = User.builder()
                    .userCode(code)
                    .username(name)
                    .password(encode)
                    .userRemark(userDTO.getRemark())
                    .updateColumn(jsonString)
                    .createDeliveryDisplay(deliveryDisplay)
                    .productDisplay(productDisplay)
                    //与操作人公司id一致
                    .companyId(operator.getCompanyId())
//                    .companyId(1)//测试
                    .build();
        }
        if(u!=null && userMapper.insert(u)>0) return ServerResponse.createBySuccess("新增用户成功");
        return ServerResponse.createByError("新增用户失败");
    }

    @Override
    public boolean updateUser(UserDTO userDTO) throws Exception{
        Integer userId = userDTO.getId();
        if(userId == null) throw new RException("用户id为空",500);
        User user = userMapper.selectById(userId);
        if(user==null) throw new RException(ResponseCode.EMPTY_ACCOUNT.getDesc(), ResponseCode.EMPTY_ACCOUNT.getCode());
        //可修改的字段
        String password = userDTO.getPassword();
        if(userDTO.getCode()!=null) user.setUserCode(userDTO.getCode());
        if(userDTO.getName()!=null) user.setUsername(userDTO.getName());
        if(password !=null){
            //密码加密
            String encode = sha1Encode(password);
            user.setPassword(encode);
        }
        if(userDTO.getRemark()!=null) user.setUserRemark(userDTO.getRemark());

        return userMapper.updateById(user)>0;
    }

    @Override
    public UserVO getUserById(Integer id) {
        if(id==null) return null;
        User user = userMapper.selectById(id);
        if(user!=null){
            return UserVO.builder()
                       .id(user.getUserId())
                       .code(user.getUserCode())
                       .name(user.getUsername())
                       .remark(user.getUserRemark())
                       .build();
        }
        return null;
    }

    @Override
    public List<UserVO> getUserList() {
        List<User> users = userMapper.selectList(null);
        if(users!=null && !users.isEmpty()){
            return users.stream()
                    .map(user -> UserVO.builder()
                        .id(user.getUserId())
                        .code(user.getUserCode())
                        .name(user.getUsername())
                        .remark(user.getUserRemark())
                        .build())
                    .collect(Collectors.toList());
        }
        return null;
    }

    /**
     * 登录
     *
     * @param username
     * @param password
     * @return token和用户名、ID
     * @throws RException
     */
    @Transactional(propagation = Propagation.REQUIRED, value = "detTransactionManager",
            rollbackFor = {Exception.class, RuntimeException.class, RException.class})
    public ServerResponse login(String username, String password) throws Exception{
        // 判空
        if (StringUtils.isEmpty(username)) {
            throw new RException(ResponseCode.EMPTY_USERNAME.getDesc(), ResponseCode.EMPTY_USERNAME.getCode());
        }
        if (StringUtils.isEmpty(password)) {
            throw new RException(ResponseCode.EMPTY_PASSWORD.getDesc(), ResponseCode.EMPTY_PASSWORD.getCode());
        }
        User user = findUsername(username);
        if(user == null){
            throw new RException(ResponseCode.EMPTY_ACCOUNT.getDesc(), ResponseCode.EMPTY_ACCOUNT.getCode());
        }
        String sha1Password = sha1Encode(password);
        if (!user.getPassword().equals(sha1Password)) {
            // 密码错误
            throw new RException(ResponseCode.ERROR_PASSWORD.getDesc(), ResponseCode.ERROR_PASSWORD.getCode());
        }
        String token = new String();
        try {
            //生成签名
            token = JWTUtil.signUser(user);
            //构造JWT Token
            JWTToken jwtToken = new JWTToken(token);
            //shiro安全框架：获取subject对象
            Subject subject = SecurityUtils.getSubject();
            //设置token
            subject.login(jwtToken);
            UserVO userVo = new UserVO();
            BeanUtils.copyProperties(user, userVo);

        } catch (Exception e) {
            //发生异常，说明登录失败
            return ServerResponse.createLoginFail("登录出错，请检查用户名、密码");
        }
        // 记录登录信息
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_code",username);
        User u = userMapper.selectOne(queryWrapper);
        SystemLog loginLog = SystemLog.builder()
                .username(u.getUsername()) // 设置登录用户名
                .operateType(0) // 设置操作类型为登录，0表示登录
                .operation("登录成功") // 设置操作说明
                .createTime(new Date()) // 设置当前时间作为操作时间
                .build();
        systemLogMapper.insert(loginLog);

        return ServerResponse.createBySuccess(user, token);
    }

    private User findUsername(String username) {
        QueryWrapper<User> wrapper = new QueryWrapper();
        wrapper.eq("user_code", username);
        User user = userMapper.selectOne(wrapper);
        return user;
    }

    @Override
    public ServerResponse logout(String username) throws RException {
        // 判空
        if (StringUtils.isEmpty(username)) {
            throw new RException(ResponseCode.EMPTY_USERNAME.getDesc(), ResponseCode.EMPTY_USERNAME.getCode());
        }
        try {
            //shiro安全框架：获取subject对象
            Subject subject = SecurityUtils.getSubject();
            //登出操作
            subject.logout();

            // 记录登出信息
            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("user_code",username);
            User u = userMapper.selectOne(queryWrapper);
            SystemLog logoutLog = SystemLog.builder()
                    .username(u.getUsername()) // 设置登出用户名
                    .operateType(1) // 设置操作类型为登出，1表示登出
                    .operation("退出系统") // 设置操作说明
                    .createTime(new Date()) // 设置当前时间作为操作时间
                    .build();
            systemLogMapper.insert(logoutLog);

        } catch (Exception e) {
            //发生异常，说明登出失败
            return ServerResponse.createByError("登出出错，请稍后再试");
        }

        return ServerResponse.createBySuccess("登出成功");
    }

    @Override
    public User findByUserCode(String username) {
        QueryWrapper<User> wrapper = new QueryWrapper();
        wrapper.eq("user_code", username);
        return userMapper.selectOne(wrapper);
    }
}




